
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "fout.h"
#include "cmd.h"
#include "sys.h"
#include "status.h"
#include "modem.h"
#include "debug.h"

xQueueHandle cmd_queue;

typedef int (*cmd_handler_t) (unsigned char cmd_source, char* args[]);


typedef struct
{
	char *cmd;
	char *usage;
	cmd_handler_t cmd_handler;
	unsigned char argc_min;			  /* arguments count */
}cmd_set_t;

int rs_handler ( unsigned char cmd_source, char* args[] )
{
	sys_reset();
	return 0;
}

extern unsigned char atd_debug_enable;

int atd_dbg_handler ( unsigned char cmd_source, char* args[] )
{
	atd_debug_enable = atoi(args[1]);

	return 0;
}
 
int test_handler ( unsigned char cmd_source, char *args[] )
{
	dbg("cmd_source: %d", cmd_source); //Dima
	fout(cmd_source,"a0: %s\r\n",args[0]); //Dima
	fout(cmd_source,"a1: %s\r\n",args[1]); //Dima
	fout(cmd_source,"a2: %s\r\n",args[2]); //Dima
	fout(cmd_source,"a3: %s\r\n",args[3]); //Dima
	fout(cmd_source,"a4: %s\r\n",args[4]); //Dima
	
	return 0;
}

int send_handler ( unsigned char cmd_source, char *args[] )
{
	unsigned char dev = atoi(args[1]);

	if ( dev == FOUT_DEV_U2 )
	{
		fout(dev,"%s\r", args[2]);
	}
	else
	{
		fout(dev,"%s", args[2]);
	}

	return 0;
}

modem_net_msg_t net_msg;

int net_handler ( unsigned char cmd_source, char *args[] )
{
	unsigned long p3;
	
	if ( args[3] == NULL )
		p3 = 0;
	else
		p3 = atoi(args[3]);

	status_set_param(args[1], args[2], p3);

	/* strcpy(net_msg.ip_addr,args[1]);  */
	/* strcpy(net_msg.port,args[2]);  */
	/* xQueueSend(modem_cmd_queue, &net_msg, portMAX_DELAY); //portMAX_DELAY */
	

	return 0;
}

const cmd_set_t cmds[] = 
{
	{"rs","",rs_handler,1},
	{"RS","",rs_handler,1},
	{"send","use: send <port num> message\r\nport number: 0,2,10\r\n",send_handler,3},
	{"atdd","use: atdd 0/1 disable/enable\r\n",atd_dbg_handler,2},
	{"test","use: test a1 a2 a3\r\n",test_handler,2},
	{"net","use: net <ip addr> <port> [send period]\r\n",net_handler,3},
	{NULL}
};


cmd_set_t* cmd_find_cmd ( char* cmd )
{
	unsigned char i;

	for(i=0; cmds[i].cmd != NULL; i++)
	{
		if ( !strcmp(cmds[i].cmd, cmd) )
		{
			return &cmds[i];
		}
	}

	return NULL;
}

void cmd_init ( void )
{
	cmd_queue = xQueueCreate( 2, sizeof(cmd_msg_t));
}

int cmd_add_cmd (unsigned char sender, const char *frm, ... )
{
	cmd_msg_t cmd;
	char *m = cmd.cmd_str; 

	va_list args;

//	vTaskSuspendAll();	
//	taskENTER_CRITICAL();

	va_start( args, frm );
	
	print(&m,frm,args);
	cmd.sender = sender;
		
	xQueueSend(cmd_queue, &cmd, portMAX_DELAY); //portMAX_DELAY

	va_end(args);

//	taskEXIT_CRITICAL();
	//xTaskResumeAll();

} 

#define   CMD_ARGS_MAX		16

typedef struct
{
	char *cmd_args[CMD_ARGS_MAX];
	unsigned char acnt;
}cmd_token_t;

#define   ARGS_DELIMITER		' '	

int cmd_parsing ( char* cmd_str, cmd_token_t *cmd, unsigned char args_max )
{
	unsigned char i;

	if ( *cmd_str == 0 || cmd_str == NULL )
		return -1;

	unsigned char delimiter = ARGS_DELIMITER;

	
	/* clear cmd_args */
	for( cmd->acnt = 0; cmd->acnt < args_max; cmd->acnt++ )
	{
		cmd->cmd_args[cmd->acnt] = NULL;
	}

	cmd->acnt = 0;

  SKIP_SPACE:
	/* skip spaces ' ' */
	while(*cmd_str != 0 && *cmd_str == delimiter)
		cmd_str++;

	if ( *cmd_str == 0 )
	{
		if ( cmd->acnt == 0 )
			return -2;
		return 0;
	}

	/* get token */
	if ( *cmd_str == '"' )
	{
		delimiter = '"';
		cmd_str++;
	}
	cmd->cmd_args[cmd->acnt++] = cmd_str++; 

	
	while(*cmd_str != 0 && *cmd_str != delimiter)
		cmd_str++;
	
	if ( *cmd_str == 0 )
		return 0;
		
	if ( *cmd_str == delimiter )
		*cmd_str++ = 0;
	
	if ( delimiter == '"' )
		delimiter = ARGS_DELIMITER;


	if ( cmd->acnt >= args_max )
		return 0;


	goto SKIP_SPACE;
	
	return 0;
}

cmd_msg_t cmd_msg;
cmd_token_t cmd_token;

void cmd_task ( void *pvParameters )
{
	unsigned int i;
	//cmd_handler_t handler;
	cmd_set_t *cmd_set;
	/* unsigned portBASE_TYPE s =uxTaskGetStackHighWaterMark(NULL); */
	/* DBG("statck size: %d",s); //Dima */

	for( ;; )
	{
		xQueueReceive(cmd_queue,&cmd_msg,portMAX_DELAY);
		dbg(">>%d; cmd: %s",cmd_msg.sender,cmd_msg.cmd_str); //Dima
		//	dbg(">>%d; cmd: %s",cmd_msg.sender,cmd_msg.buf); //Dima

		if ( cmd_parsing(cmd_msg.cmd_str, &cmd_token, CMD_ARGS_MAX) == 0 )
		{
			cmd_set = cmd_find_cmd(cmd_token.cmd_args[0]);
			
			if ( cmd_set != NULL )
			{
				if ( cmd_token.acnt >= cmd_set->argc_min )
				{
					cmd_set->cmd_handler(cmd_msg.sender, cmd_token.cmd_args);
				}
				else
				{
					fout(cmd_msg.sender,cmd_set->usage); //Dima
				}
			}
			else
			{
				fout(cmd_msg.sender,"\r\n%s: command not found\r\n",cmd_token.cmd_args[0]); //Dima
			}
		}
	}
}

